﻿using System;
using System.Collections.Generic;
using System.Text;
using VCDIFF.Visit;

namespace VCDIFF.Commands
{
    ///<summary>
    /// ADD: This instruction has two arguments, a size x and a sequence of x bytes to be copied.
    ///</summary>
    public class Add : Command
    {
        public UInt64 Size { get; set; }
        public byte[] Sequence { get; set; }

        /// <summary>
        /// Add constructor.
        /// </summary>
        /// <param name="size">Size of data to add.</param>
        /// <param name="sequence">Byte table to add.</param>
        public Add(UInt64 size, byte[] sequence)
        {
            Size = size;
            Sequence = sequence;            
        }

        /// <summary>
        /// Execute the add command on the target byte table.
        /// </summary>
        /// <param name="target">Byte table on which we proceed the command.</param>
        /// <returns>Byte table on which the command was done.</returns>
        public override byte[] Execute(byte[] target)
        {
            byte[] addArray = new byte[(UInt64)target.LongLength + Size];

            int index = 0;

            for (int i = 0; i < target.Length; i++)
            {
                addArray[i] = target[i];
                index++;
            }

            int sequenceIndex = 0;

            for (int i = index; i < addArray.Length; i++)
            {
                addArray[i] = Sequence[sequenceIndex];
                sequenceIndex++;
            }

            return addArray;
        }

        /// <summary>
        /// Returns the encoded byte table of the add command.
        /// </summary>
        /// <returns>The encoded byte table of the add command.</returns>
        public override byte[] ToByteArray()
        {
            byte[] addArray = new byte[Sequence.Length + 2];
            addArray[0] = 0x01;
            addArray[1] = Convert.ToByte(Size);

            for (int i = 0; i < Sequence.Length; i++)
                addArray[i + 2] = Sequence[i];

            return addArray;
        }

        /// <summary>
        /// Writes Add command thanks to a Writer.
        /// </summary>
        /// <param name="writer">Writer who writes Add command.</param>
        public override void Write(Writer writer)
        {
            writer.Visit(this);
        }

        /// <summary>
        /// Accepts a reader and authorizes it to visit this object.
        /// </summary>
        /// <param name="writer">Reader which visits this object.</param>
        public override void Read(Reader reader)
        {
            reader.Visit(this);
        }
    }
}
